package com.lizemin.proxy;

import cn.hutool.json.JSONUtil;
import com.lizemin.entity.User;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author lzm
 * @date 2025/5/16 22:18
 * @description
 */
@Slf4j
public class CglibProxy implements ProxyFactory {

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clazz) {
        // 创建 Enhancer 对象
        Enhancer enhancer = new Enhancer();
        // 设置目标类的字节码对象
        enhancer.setSuperclass(clazz);
        // 设置方法拦截器
        enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
            switch (method.getName()) {
                case "getUserById":
                    if (args[0] == null) {
                        throw new IllegalArgumentException("id不能为空！");
                    }
                    Integer id = (Integer) args[0];
                    log.info("开始从数据库中查询id为{}的用户信息！", id);
                    return getUser(id); // 返回方法执行后的结果
                case "getAllUsers":
                    log.info("开始从数据库中查询所有用户信息！");
                    return queryUsers();
                case "toString":
                    return "userMapper";
            }
            return null;
        });
        // 创建代理对象
        return (T) enhancer.create();
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Object target) {
        // 创建 Enhancer 对象
        Enhancer enhancer = new Enhancer();
        // 设置目标类的字节码对象
        enhancer.setSuperclass(target.getClass());
        // 设置方法拦截器
        enhancer.setCallback(getMethodInterceptor());
        // 创建代理对象
        return (T) enhancer.create();
    }

    /**
     * 获取方法拦截器
     * 有没有觉得这段代码和我们写的aop切面很类似？
     *
     * @return 方法拦截器
     */
    private static MethodInterceptor getMethodInterceptor() {
        return (obj, method, args, proxy) -> {
            log.info("请求的方法名为：{},请求的参数为：{}", method.getName(), Arrays.toString(args));
            Object result = proxy.invokeSuper(obj, args);
            log.info("方法的返回值为：{}", JSONUtil.toJsonPrettyStr(result));
            return result;
        };
    }

    private static User getUser(Integer id) {
        User user = new User();
        user.setId(id);
        user.setName("csdn");
        user.setAge(20);
        return user;
    }

    private static ArrayList<User> queryUsers() {
        int id;
        ArrayList<User> users = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            id = i + 1;
            User user = new User();
            user.setId(id);
            user.setName("csdn—" + id);
            user.setAge(20 + i);
            users.add(user);
        }
        return users;
    }

}
